/*
 * Funny Language - a free style programming language.
 * Copyright (C) 2015 by fanguangping (fanguangping@163.com)
 * operator.h
 */

#ifndef OPERATOR_H_
#define OPERATOR_H_

#include <unistd.h>
#include "../../ds/datastructure.h"
#include "ds.h"
#include "basic.h"
#include "memory.h"
#include "../atoms/atom.h"
#include "../atoms/boolean.h"
#include "../atoms/character.h"
#include "../atoms/integer.h"
#include "../atoms/number.h"
#include "../atoms/tstring.h"
#include "../atoms/symbol.h"
#include "../atoms/decimal.h"
#include "../atoms/fraction.h"
#include "../atoms/real.h"
#include "../atoms/complex.h"
#include "../io/read.h"
#include "../io/write.h"
#include "../syntax/control.h"
#include "../syntax/define.h"
#include "../syntax/eval.h"
#include "../syntax/let.h"
#include "../syntax/logic.h"
#include "../syntax/promise.h"
#include "../types/class.h"
#include "../types/closure.h"
#include "../types/continuation.h"
#include "../types/environment.h"
#include "../types/exception.h"
#include "../types/list.h"
#include "../types/object.h"
#include "../types/pair.h"
#include "../types/procedure.h"
#include "../types/syntax.h"
#include "../types/vector.h"

#define CONSTANT_NAME_NIL    "*nil*"

#define TYPE_CHECK(sc, obj, type)    if (!type_of(sc, obj, type)) { \
	sc->returnValue = make_default_exception_1(sc, "INVALID_TYPE", "Object is not of type %s.", type); \
	return pop_callstack(sc); }

#define TYPE_CHECK_FOR_CELL(sc, obj, type)    if (!type_of(sc, obj, type)) { \
	return make_default_exception_1(sc, "INVALID_TYPE", "Object is not of type %s.", type); }

#define PRIVILEGE_CHECK(sc)    if(geteuid() != 0) \
	return make_default_exception(sc, "PRIVILEGE_DENY", "You should run as root!\n")

#define ADD_OPERATOR(sc, name, opname)  cell_op_##opname = make_procedure(sc, op_##opname); add_constant(sc, name, cell_op_##opname)
#define ADD_SYNTAX(sc, name, syntaxop)    add_syntax(sc, name, cell_op_##syntaxop)

void init_global_symbols(Scheme *sc);
void init_global_syntaxes(Scheme *sc);
void init_global_operators(Scheme *sc);
void init_global_constants(Scheme *sc);

void add_constant(Scheme *sc, const char *name, Cell *value);
void add_syntax(Scheme *sc, const char *name, Cell *value);
Cell* eval(Scheme *sc, String statement);
int scheme_init(Scheme *sc);

#endif /* OPERATOR_H_ */
